/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package at.irian.demo.jsfatwork.view.page;

import at.irian.demo.jsfatwork.domain.User;
import at.irian.demo.jsfatwork.service.UserService;
import at.irian.demo.jsfatwork.view.PageBean;
import at.irian.demo.jsfatwork.view.security.UserHolder;
import at.irian.demo.jsfatwork.view.UserQualifier;
import at.irian.demo.jsfatwork.view.exception.UILockDownException;
import org.apache.myfaces.extensions.validator.baseval.annotation.Required;
import static org.apache.myfaces.extensions.validator.core.validation.parameter.ViolationSeverity.Fatal;
import org.apache.myfaces.extensions.validator.crossval.annotation.Equals;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.inject.Inject;
import javax.inject.Provider;

/**
 * @author Gerhard Petracek
 */
@PageBean
public class LoginPage extends AbstractPage
{
    @Inject
    @UserQualifier
    private Provider<User> userProvider;

    private User currentUser;

    @Inject
    private UserHolder userHolder;

    @Required(parameters = Fatal.class)
    @Equals(value = "repeatedPassword",
            parameters = Fatal.class)
    private String newPassword;

    @Required(parameters = Fatal.class)
    private String repeatedPassword;

    @Required(parameters = Fatal.class)
    private String password;

    @Required(parameters = Fatal.class)
    private String userName;

    @Inject
    private UserService userService;

    private int invalidLoginCount = 0;

    private static final int INVALID_LOGIN_COUNT_MEDIUM = 7;
    private static final int INVALID_LOGIN_COUNT_HIGH = 10;
    private static final int INVALID_LOGIN_COUNT_LOCKDOWN = 20;

    @PostConstruct
    public void preparePageForRendering()
    {
        this.currentUser = this.userProvider.get();
    }

    public String register()
    {
        this.currentUser.setPassword(this.newPassword);

        this.userService.save(this.currentUser);
        this.userHolder.setCurrentUserName(this.currentUser.getUserName());

        cleanup();
        this.userHolder.reset();

        return "pages/login";
    }

    public String login()
    {
        if (this.invalidLoginCount > INVALID_LOGIN_COUNT_LOCKDOWN)
        {
            throw new UILockDownException("lockdown");
        }

        if (this.userService.isLoginPermitted(this.userName, this.password))
        {
            this.userHolder.setCurrentUserName(this.userName);
            this.invalidLoginCount = 0;
        }
        else
        {
            checkForInvalidLogins();
            this.invalidLoginCount++;
            return null;
        }

        return "pages/home";
    }

    private void checkForInvalidLogins()
    {
        if (this.invalidLoginCount <= INVALID_LOGIN_COUNT_MEDIUM)
        {
            addMessage(FacesMessage.SEVERITY_ERROR, "access denied");
        }
        if (this.invalidLoginCount > INVALID_LOGIN_COUNT_MEDIUM && this.invalidLoginCount <= INVALID_LOGIN_COUNT_HIGH)
        {
            addMessage(FacesMessage.SEVERITY_ERROR, "please contact the administrator!");
        }
        else if (this.invalidLoginCount > INVALID_LOGIN_COUNT_HIGH && this.invalidLoginCount <= INVALID_LOGIN_COUNT_LOCKDOWN)
        {
            addLockdownMessage();
        }
    }

    private void addLockdownMessage()
    {
        addMessage(FacesMessage.SEVERITY_FATAL, "[locked down] go away!");
    }

    /*
     * generated
     */
    public User getCurrentUser()
    {
        return currentUser;
    }

    public String getNewPassword()
    {
        return newPassword;
    }

    public void setNewPassword(String newPassword)
    {
        this.newPassword = newPassword;
    }

    public String getRepeatedPassword()
    {
        return repeatedPassword;
    }

    public void setRepeatedPassword(String repeatedPassword)
    {
        this.repeatedPassword = repeatedPassword;
    }

    public String getPassword()
    {
        return password;
    }

    public void setPassword(String password)
    {
        this.password = password;
    }

    public String getUserName()
    {
        return userName;
    }

    public void setUserName(String userName)
    {
        this.userName = userName;
    }
}
